#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#define SIZE 256

/*重定向*/
void check(char* buf)
{
    int count = 0; 
    char* file = NULL;
    for( ; *buf!='\0' ; buf++ )
    {
        if( *buf == '>' )
        {
            *buf='\0';
            buf++;
            count++;
            
            if(*buf == '>' ) count++;
            *buf='\0';
            buf++;
            while( *buf!='\0' && *buf==' ' ) buf++ ;
            file=buf;
            while( *buf!='\0' && *buf!=' ') buf++;
            *buf='\0';
        }

        if( count == 1 )
        {
           int fd = open(file,O_CREAT|O_TRUNC|O_WRONLY,0666);
           dup2(fd,1);
        }
        else if( count == 2 )
        {
           int fd = open(file,O_CREAT|O_APPEND|O_WRONLY,0666);
           dup2(fd,1);
        }
        else if( count > 2 )
        {
            return ;
        }
    }
}

void check2(char* buf)
{
    int count = 0; 
    char* file = NULL;
    for( ; *buf!='\0' ; buf++ )
    {
        if( *buf == '<' )
        {
            *buf='\0';
            buf++;
            count++;
            while( *buf!='\0' && *buf==' ' ) buf++ ;
            file=buf;
            while( *buf!='\0' && *buf!=' ') buf++;
            *buf='\0';
        }
        if( count == 1 )
        {
           int fd = open(file,O_RDONLY);
           dup2(fd,0);
        }
        else if( count > 2 )
        {
            return ;
        }
    }
}
/*假设一个匿名管道*/
void checkpipe(char * buf)
{
     char* st = buf;
     for( ; *buf!='\0'; buf++ )
     {
         if(*buf == '|')
         {
            *buf='\0';buf++;
            int pipefd[2]; 
            pipe(pipefd);
            pid_t id = fork(); 

            if( id == 0 )//child
            {
                close(pipefd[0]);
                dup2(pipefd[1],1);
                _exec(st);
            }
            else{//father
                close(pipefd[1]);
                dup2(pipefd[0],0);
                _exec(buf);
            }
         }
     }
}
void _exec(char* buf){

      char* argvs[SIZE]={NULL};
      char* str = strtok(buf," ");
      int count = 0 ;

      while(str!=NULL)
      {
         argvs[ count++ ] = str;
         str = strtok (NULL," ");
      } 
      execvp(argvs[0],argvs);
      exit(1);
}
int main(){
   const char* str="abc@VM-12-8centos minishell# ";
   char* buf[SIZE];
   while(1)
   {
       printf("%s",str);
       fflush(stdout);
       pid_t pid=fork(); 

       if( pid == 0 )
       {
          gets(buf);
          buf[strlen(buf)]='\0';

          check(buf);
          check2(buf);
          checkpipe(buf); 
          _exec(buf);
       }
       else{
          int status;
          waitpid(pid,&status,0);
          if(status&0x7F){
              printf("error signal:%d\n",status&0x7f);   
          }
          else{
              printf("exit code:%d\n",(status>>8)&0xff);    
          }
       }
   }
   return 0;
}
